home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / swaptp.zip / SWAPA.ASM < prev    next >
Assembly Source File  |  1991-11-06  |  29KB  |  673 lines

  1. ;**************************************************************************;
  2. ;*                           S W A P A . A S M                            *;
  3. ;*------------------------------------------------------------------------*;
  4. ;*    Task           : Assembler module for the SWAP unit                 *;
  5. ;*------------------------------------------------------------------------*;
  6. ;*    Author         : MICHAEL TISCHER                                    *;
  7. ;*    developed on   :  06/01/1989                                        *;
  8. ;*    last update    :  02/28/1990                                        *;
  9. ;*------------------------------------------------------------------------*;
  10. ;*    assembly       : TASM - /MX SWAPA                              *;
  11. ;*                     ... bind to the SWAP unit                          *;
  12. ;**************************************************************************;
  13.  
  14. ;== Constants ===============================================================
  15.  
  16. STACK_LEN  equ 64                 ;Number of words in the internal stack
  17.  
  18. ;== Structures =============================================================
  19.  
  20. ExecStruc struc                   ;Data structure for EXEC function
  21. EsSegEnv  dw ?                    ;Segment address of environment blocks
  22. EsCmdPAdr dd ?                    ;Pointer to command line parameters
  23. EsFCB1Adr dd ?                    ;Pointer to FCB #1
  24. EsFCB2Adr dd ?                    ;Pointer to FCB #2
  25.  
  26. ExecStruc ends
  27.  
  28. ;== Data segment ===========================================================
  29.  
  30. DATA   segment word public
  31.  
  32. extrn  PrefixSeg : word           ;Segment address of PSP in Turbo variables
  33.  
  34. DATA   ends
  35.  
  36. ;== Program ===============================================================
  37.  
  38. CODE       segment byte public    ;Program segment
  39.  
  40. public     SwapOutAndExec         ;Gives a Turbo Pascal program the
  41.                                   ;ability to pass the address of
  42.                                   ;the assembler handler
  43. public     InitSwapa              ;Initialization procedure
  44.  
  45. ;== Variables in code segment ===============================================
  46.  
  47. CodeStart  equ this byte          ;Code begins here which is copied to
  48.                                   ;the Turbo program
  49.  
  50. ;-- Variables needed by the Swap routines for uploading and downloading ----
  51.  
  52. CoStAddr   dd ?                   ;Orig. address of PARA(CodeStart)
  53. CoStLen    dw ?                   ;Number of words swapped w/ CoStAddr
  54. StackPtr   dw ?                   ;Gets old stack pointer
  55. StackSeg   dw ?                   ;Gets old stack segment
  56. TurboSeg   dw ?                   ;Segment address - Turbo code segment
  57.  
  58. ;-- Variables needed for program configuration and command execution -------
  59.  
  60. NewStack   dw STACK_LEN dup (?)   ;New stack
  61. EndStack   equ this word          ;End of stack
  62.  
  63. Command    dd ?                   ;Pointer to command
  64. CmdPara    dd ?                   ;Pointer to command line parameters
  65. ToDisk     db ?                   ;True when disk swapping occurs
  66. Handle     dw ?                   ;Disk or EMS handle
  67. Len        dd ?                   ;Number of bytes saved
  68.  
  69. FCB1       db  16 dup ( 0 )       ;FCB #1 for PSP
  70. FCB2       db  16 dup ( 0 )       ;FCB #2 for PSP
  71. CmdBuf     db 128 dup ( 0 )       ;Commands following prg. name
  72. PrgName    db  64 dup ( 0 )       ;Program name
  73. ExecData   ExecStruc < 0, CmdBuf, FCB1, FCB2 >   ;Data structure for EXEC
  74.  
  75. OldPara    dw ?                   ;Number of previously reserved paragraphs
  76. FrameSeg   dw ?                   ;Segment address of EMS page frame
  77. Error_Code db 0                   ;Error code for caller
  78.  
  79. TerMes     db 13,10,13,10
  80.            db "╔═══════════════════════════════════════════════════╗",13,10
  81.            db "║ SWAP : Stored Turbo Pascal program could          ║",13,10
  82.            db "║        not be reloaded back into memory.          ║",13,10
  83.            db "║        Program execution terminated!              ║",13,10
  84.            db "╚═══════════════════════════════════════════════════╝"
  85.            db 13,10,13,10,"$"
  86.  
  87. ;== Procedures =============================================================
  88.  
  89. ;---------------------------------------------------------------------------
  90. ;-- StartSwap : Coordinate swapping of Turbo Pascal program
  91.  
  92. StartSwap  proc far
  93.  
  94.            assume cs:code, ds:nothing
  95.  
  96.            ;-- Store current stack and initialize new stack ----------------
  97.  
  98.            cli                    ;Suppress interrupts
  99.            mov   StackPtr,sp      ;Mark current stack
  100.            mov   StackSeg,ss
  101.            push  cs               ;Install new stack
  102.            pop   ss
  103.            mov   sp,offset EndStack - 2
  104.            sti                    ;Re-enable interrupts
  105.  
  106.            push  cs               ;Set DS to CS
  107.            pop   ds
  108.            assume cs:code, ds:code
  109.  
  110.            ;-- Overwrite unnecessary memory --------------------------------
  111.  
  112.            cmp   ToDisk,0         ;Write to EMS memory?
  113.            je    Ems              ;Yes ---> Ems
  114.  
  115.            call  Write2File       ;No ---> Write to file
  116.            jnc   ShrinkMem        ;No error ---> ShrinkMem
  117.  
  118.            mov   Error_Code, 1    ;File output error?
  119.            jmp   short GetBack    ;return to Turbo
  120.  
  121. Ems:       mov   ah,41h           ;Pass segment address of the page frame
  122.            int   67h              ;Call EMM
  123.            mov   FrameSeg,bx      ;Place result in variables
  124.  
  125.            call  Write2Ems        ;Write program to EMS
  126.  
  127.            ;-- Provide number of currently allocated paragraphs ------------
  128.  
  129. ShrinkMem: mov   ax,TurboSeg      ;Segment address of Turbo code segment
  130.            sub   ax,11h           ;Allocate 10 paragraphs for PSP and 1
  131.                                   ;for MCB
  132.            mov   es,ax            ;ES now pointer to Turbo prog. MCB
  133.            mov   bx,es:[3]        ;Get number of paragraphs allocated
  134.            mov   OldPara,bx       ;and place in variable
  135.  
  136.            ;-- Calculate the number of paragraphs needed and reduce  --
  137.            ;-- memory requirements by this amount                    --
  138.  
  139.            inc   ax               ;AX now points to the PSP
  140.            mov   es,ax            ;for function call to ES
  141.            mov   bx,CostLen       ;Number of words needed by Swap routine
  142.            add   bx,128+7         ;Recalculate and round off PSP
  143.            mov   cl,3             ;Divide by 8 words (per paragraph)
  144.            shr   bx,cl
  145.  
  146.            mov   ah,4Ah           ;Function number for "change size"
  147.            int   21h              ;Call DOS interrupt
  148.  
  149.            ;-- Execute specified command line using the EXE function ------
  150.  
  151.            mov   bp,ds            ;Store DS 
  152.  
  153.            mov   ax,cs            ;Set ES and DS to CS
  154.            mov   es,ax
  155.            mov   ds,ax
  156.  
  157.            ;-- Enter segment address of code segments in the pointer -----
  158.            ;-- to the EXEC structure
  159.  
  160.            mov   word ptr ExecData.EsFCB1Adr + 2,ax
  161.            mov   word ptr ExecData.EsFCB1Adr + 2,ax
  162.            mov   word ptr ExecData.EsCmdPAdr + 2,ax
  163.  
  164.            mov   bx,offset ExecData  ;ES:BX point to parameter block
  165.            mov   dx,offset PrgName   ;DS:DX point to command string
  166.  
  167.            mov   ax,4B00h         ;Function number for "EXEC"
  168.            int   21h              ;Call DOS interrupt
  169.            mov   ds,bp            ;Move DS
  170.            jnc   ReMem            ;No error ---> ReMem
  171.  
  172.            mov   Error_Code,ah    ;Note ErrorCode
  173.  
  174.            ;-- Return memory to original size ------------------------------
  175.  
  176. ReMem:     mov   ax,TurboSeg      ;Set Turbo code segment address
  177.            sub   ax,10h           ;to start of PSP
  178.            mov   es,ax            ;and load into ES
  179.            mov   bx,OldPara       ;Old number of paragraphs
  180.  
  181.            mov   ah,4Ah           ;Function number for "change size"
  182.            int   21h              ;Call DOS interrupt
  183.            jnc   GetBack          ;No error ---> GetBack
  184.  
  185.            jmp   Terminate        ;Error in ReMem --> End program
  186.  
  187.            ;-- Return to program -------------------------------------------
  188.  
  189. GetBack:   cmp   ToDisk,0         ;Write to EMS memory?
  190.            je    Ems1             ;Yes ---> Ems1
  191.  
  192.            call  GetFromFile      ;No, reload as file
  193.            jnc   CloseUp          ;No error ---> CloseUp
  194.  
  195.            jmp   Terminate        ;Read error, end program
  196.  
  197. Ems1:      call  GetFromEms       ;Get Turbp Pascal program from EMS memory
  198.  
  199.            ;-- Restore old stack -------------------------------------------
  200.  
  201. CloseUp:   cli                    ;Suppress interrupts
  202.            mov   ss,StackSeg
  203.            mov   sp,StackPtr
  204.            sti                    ;Re-enable interrupts
  205.  
  206.            ;-- Prepare registers for swap ----------------------------------
  207.  
  208.            push  cs                       ;Push DS to CS
  209.            pop   ds
  210.            assume cs:code, ds:code
  211.  
  212.            mov   cx,CoStLen               ;Number of words to be swapped
  213.            mov   di,cx                    ;Move number of words to DI
  214.            dec   di                       ;Decrement by one word
  215.            shl   di,1                     ;Double it
  216.            mov   si,di                    ;move to SI
  217.            add   di,word ptr CostAddr     ;DI+offset addr. of Swap routine
  218.            mov   es,word ptr CostAddr + 2 ;ES gets old CS of Swap routine
  219.            mov   ds,TurboSeg              ;Seg addr. of start of code
  220.  
  221.            ret                            ;Return to SwapOutAndExec
  222.  
  223. StartSwap  endp
  224.  
  225. ;---------------------------------------------------------------------------
  226. ;-- Write2Ems : Write program to be swapped to EMS memory
  227. ;-- Input     : BX = Segment address of EMS page frame
  228. ;--             DS = Codesegment
  229.  
  230. EMS_PLEN   equ 16384                   ;Length of an EMS page
  231.  
  232. HiWLen     dw    ?                     ;Remaining Hi-Word length
  233.  
  234. Write2Ems  proc near
  235.  
  236.            push  ds                    ;Push DS onto stack
  237.            cld                         ;Increment on string instructions
  238.            mov   es,bx                 ;ES points to the page frame
  239.  
  240.            mov   bp,word ptr Len       ;Move Lo-Word length to BP
  241.            mov   ax,word ptr Len + 2   ;Move Hi-Word length to AX
  242.            mov   HiWLen,ax             ;and then to variable
  243.  
  244.            mov   dx,Handle             ;Move EMS Handle to DX
  245.            xor   bx,bx                 ;Start with first logical page
  246.  
  247.            assume cs:code, ds:nothing
  248.  
  249.            jmp short WriECalc          ;Jump in the loop
  250.  
  251. WriELoop:  ;-- Register allocation within this loop -----------------------
  252.            ;
  253.            ;  AX        = Times this, times that
  254.            ;  BX        = Number of logical EMS pages to be addressed
  255.            ;  CX        = Number of bytes to be copied in this execution
  256.            ;  DX        = EMS handle
  257.            ;  ES:DI     = Pointer to first page in EMS page frame (Target)
  258.            ;  DS:SI     = Pointer to first word to be copied      (Start)
  259.            ;  HiWLen:BP = Number of bytes remaining to be copied
  260.  
  261.            mov   ax,4400h              ;Function number for illustration
  262.            int   67h                   ;Call EMM
  263.  
  264.            mov   si,offset CodeEnd     ;Offset for Swapping
  265.            xor   di,di                 ;Write to the start of the EMS page
  266.            mov   ax,cx                 ;Move number to AX
  267.            rep movsb                   ;Copy memory
  268.  
  269.            sub   bp,ax                 ;Remainder of written bytes
  270.            sbb   HiWLen,0              ;Decrement
  271.  
  272.            inc   bx                    ;Increment number of logical page
  273.  
  274.            mov   ax,ds                 ;Starting segment to AX
  275.            add   ax,EMS_PLEN shr 4     ;Increment by written paragraphs
  276.            mov   ds,ax                 ;and move to DS
  277.  
  278. WriECalc:  mov   cx,EMS_PLEN           ;Write EMS_PLEN bytes
  279.            cmp   HiWLen,0              ;More than 64K?
  280.            ja    WriELoop              ;Yes ---> WriELoop
  281.            cmp   bp,cx                 ;No ---> More than EMS_PLEN bytes?
  282.            jae   WriELoop              ;Yes ---> Continue writing
  283.            mov   cx,bp                 ;No ---> Write remainder
  284.            or    cx,cx                 ;No more bytes to write?
  285.            jne   WriELoop              ;No ---> WriELoop
  286.  
  287. WriERet:   pop   ds                    ;Pop DS off of stack
  288.            ret                         ;Return to caller
  289.  
  290. Write2Ems  endp
  291.  
  292. ;---------------------------------------------------------------------------
  293. ;-- GetFromEms : Get the swapped program from EMS memory
  294. ;-- Input   : DS = Code segment
  295.  
  296. GetFromEms proc near
  297.  
  298.            push  ds                    ;Push DS onto the stack
  299.            cld                         ;Increment on string instructions
  300.  
  301.            mov   bp,word ptr Len       ;Move Lo-Word length to BP
  302.            mov   ax,word ptr Len + 2   ;Move Hi-Word length to AX
  303.            mov   HiWLen,ax             ;and from there to variable
  304.  
  305.            mov   dx,Handle             ;Move EMS handle to DX
  306.            xor   bx,bx                 ;Start with first logical page
  307.  
  308.            mov   ds,FrameSeg           ;DS points to the page frame
  309.            push  cs                    ;Set ES to the code segment
  310.            pop   es
  311.  
  312.            assume cs:code, ds:nothing
  313.  
  314.            jmp short GetECalc          ;Jump to the loop
  315.  
  316. GetELoop:  ;-- Register allocation within this loop -----------------------
  317.            ;
  318.            ;  AX        = times this, times that
  319.            ;  BX        = Number of logical EMS pages to be swapped
  320.            ;  CX        = Number of bytes to be copied in this execution
  321.            ;  DX        = EMS handle
  322.            ;  DS:SI     = Pointer to first page in EMS page frame (Start)
  323.            ;  ES:DI     = Pointer to target address in memory
  324.            ;  HiWLen:BP = Number of bytes still to be copied
  325.  
  326.            mov   ax,4400h              ;Function number for illustration
  327.            int   67h                   ;Call EMM
  328.  
  329.            mov   di,offset CodeEnd     ;Offset for Swapping
  330.            xor   si,si                 ;Write to the start of the EMS page
  331.            mov   ax,cx                 ;Move number to AX
  332.            rep movsb                   ;Copy memory
  333.  
  334.            sub   bp,ax                 ;Remainder of written bytes
  335.            sbb   HiWLen,0              ;Decrement
  336.  
  337.            inc   bx                    ;Increment number of logical page
  338.  
  339.            mov   ax,es                 ;Move starting segment to AX
  340.            add   ax,EMS_PLEN shr 4     ;Increment by written paragraphs
  341.            mov   es,ax                 ;and move it to ES
  342.  
  343. GetECalc:  mov   cx,EMS_PLEN           ;Write EMS_PLEN bytes
  344.            cmp   HiWLen,0              ;More than 64K?
  345.            ja    GetELoop              ;Yes ---> GetELoop
  346.            cmp   bp,cx                 ;No ---> More than EMS_PLEN bytes?
  347.            jae   GetELoop              ;Yes ---> Continue writing
  348.            mov   cx,bp                 ;No ---> Write remainder
  349.            or    cx,cx                 ;No more bytes to write?
  350.            jne   GetELoop              ;No ---> GetELoop
  351.  
  352. GetERet:   pop   ds                    ;Pop DS off of stack
  353.            ret                         ;Return to caller
  354.  
  355. GetFromEms endp
  356.  
  357. ;---------------------------------------------------------------------------
  358. ;-- Write2File : Write the program to be swapped to a file
  359. ;-- Returns    : Carry-Flag = 1 : Error
  360.  
  361. Write2File proc near
  362.  
  363. NUM_WRITE  = 2048                      ;Bytes to be written per execution
  364.                                        ;to power of 2 (max. 2^16)
  365.            assume cs:code, ds:code
  366.  
  367.            push  ds                    ;Push DS onto stack
  368.            mov   bp,4000h              ;Function number for "Write"
  369.            mov   bx,Handle             ;Load file handle
  370.  
  371. WriFStart: mov   di,word ptr Len       ;Move Lo-Word length to DI
  372.            mov   si,word ptr Len + 2   ;Move Hi-Word length to SI
  373.            mov   dx,offset CodeEnd     ;Write offset address
  374.            jmp   short WriFCalc        ;Compute no. of bytes to be written
  375.  
  376. WriFLoop:  ;-- Register allocation within this loop -----------------
  377.            ;
  378.            ;  AX        = times this, times that
  379.            ;  BX        = DOS file handle
  380.            ;  CX        = Number of bytes to be read/written
  381.            ;  DS:DX     = Address at which they should be read/written
  382.            ;  DI:SI     = Number of bytes still to be copied
  383.            ;  BP        = Number of DOS funtion to be called
  384.  
  385.            mov   ax,bp                 ;Load DOS function number
  386.            int   21h                   ;Call DOS interrupt
  387.            jc    WriFEnd               ;Error ---> WriFEnd
  388.            mov   ax,ds                 ;Starting segment to AX
  389.            add   ax,NUM_WRITE shr 4    ;Increment by written paragraphs
  390.            mov   ds,ax                 ;and move to DS
  391.            sub   di,cx                 ;Decrement remainder of
  392.            sbb   si,0                  ;written bytes
  393.  
  394. WriFCalc:  mov   cx,NUM_WRITE          ;Write NUM_WRITE bytes
  395.            cmp   si,0                  ;More than 64K?
  396.            ja    WriFLoop              ;Yes ---> WriFLoop
  397.            cmp   di,cx                 ;No ---> More than NUM_WRITE bytes?
  398.            jae   WriFLoop              ;Yes ---> Continue writing
  399.            mov   cx,di                 ;No ---> Write remainder
  400.            or    cx,cx                 ;No more bytes to write?
  401.            jne   WriFLoop              ;No ---> WriFLoop
  402.  
  403. WriFEnd:   pop   ds                    ;Reload DS
  404. WriFRet:   ret                         ;Return to caller
  405.  
  406. Write2File endp
  407.  
  408. ;---------------------------------------------------------------------------
  409. ;-- GetFromFile : Return the swapped program to memory
  410. ;-- Returns    : Carry-Flag = 1 : Error
  411.  
  412. GetFromFile proc near
  413.  
  414.            assume cs:code, ds:code
  415.  
  416.            push  ds               ;Push DS onto the stack
  417.  
  418.            ;-- Move file pointer to the start of file ----------------
  419.  
  420.            mov   ax,4200h         ;DOS function number
  421.            mov   bx,Handle        ;Load file handle
  422.            xor   cx,cx            ;CX:DX gives its position
  423.            mov   dx,cx
  424.            int   21h              ;Call DOS interrupt
  425.            jc    WriFRet          ;Error ---> WriFRet
  426.  
  427.            ;-- Load file into memory with the help of Write2File -----
  428.  
  429.            mov   bp,3F00h         ;Function number for "Read"
  430.            jmp   WriFStart        ;Jump to Write2File
  431.  
  432. GetFromFile endp
  433.  
  434. ;---------------------------------------------------------------------------
  435. ;-- Terminate : The system can't return to the original Turbo Pascal
  436. ;--             program. The program ends with an error code.
  437.  
  438. Terminate  label near
  439.  
  440.            ;-- Display error message ---------------------------------------
  441.  
  442.            push  cs               ;Set DS to CS
  443.            pop   ds
  444.            mov   dx,offset TerMes ;DS:DX points to the error message
  445.            mov   ah,9             ;Function number for "Display string"
  446.            int   21h              ;Display DOS interrupt
  447.  
  448.            mov   ax,4C01h         ;End program with error code
  449.            int   21h
  450.  
  451.  
  452. ;===========================================================================
  453.  
  454. CodeEnd    equ this byte          ;Copy code from the start of the Turbo
  455.                                   ;Pascal program to this point
  456.  
  457. ;---------------------------------------------------------------------------
  458. ;-- SwapOutAndExec : Swaps the current program to EMS memory or hard disk
  459. ;--                  and starts another program using the DOS EXEC function
  460. ;-- Call from Turbo: SwapOutAndExec( Command,
  461. ;--                                CmdPara : string;
  462. ;--                                ToDisk  : boolean;
  463. ;--                                Handle  : word;
  464. ;--                                Len     : longint );
  465. ;-- Info         : The Command and CmdPara parameters must be configured
  466. ;--                as strings in DOS format.
  467.  
  468. SwapOutAndExec proc near
  469.  
  470. ACommand   equ dword ptr [bp+16]  ;Constants for accessing the
  471. ACmdPara   equ dword ptr [bp+12]  ;specified arguments
  472. AToDisk    equ  byte ptr [bp+10]
  473. AHandle    equ  word ptr [bp+ 8]
  474. ALen       equ dword ptr [bp+ 4]
  475. ARG_LEN    equ 16                 ;Lengths of arguments
  476.  
  477.            assume cs:code, ds:data
  478.  
  479.            push  bp               ;Enable access to the arguments
  480.            mov   bp,sp
  481.  
  482.            ;-- Copy program name to buffer in code segment -----------------
  483.  
  484.            mov   dx,ds            ;Mark DS 
  485.            push  cs               ;Set ES to CS
  486.            pop   es
  487.  
  488.            lds   si,ACommand      ;DS:SI points to command buffer
  489.            mov   di,offset PrgName ;ES:DI points to PrgName
  490.            cld                    ;Increment on string instructions
  491.            lodsb                  ;Read length of Pascal string
  492.            cmp   al,64            ;More than 64 characters?
  493.            jbe   CmdCopy          ;No ---> CmdCopy
  494.  
  495.            mov   al,64            ;Yes ---> Copy a maximum of 64 characters
  496.  
  497. CmdCopy:   xor   ah,ah            ;Set Hi-Byte to 0 length and
  498.            mov   cx,ax            ;load into the counter
  499.            rep movsb              ;Copy string
  500.  
  501.            ;-- Copy command line in buffer in code segment -----------------
  502.  
  503.            lds   si,ACmdPara      ;DS:SI points to CmdPara buffer
  504.            mov   di,offset CmdBuf ;ES:DI points to CmdBuf
  505.            lodsb                  ;Read length of Pascal string
  506.            cmp   al,126           ;More than 126 characters?
  507.            jbe   ParaCopy         ;No ---> ParaCopy
  508.  
  509.            mov   al,126           ;Yes ---> Copy maximum of 126 characters
  510.  
  511. ParaCopy:  stosb                  ;Store length as first byte
  512.            xor   ah,ah            ;Set Hi-Byte to 0 length and
  513.            mov   cx,ax            ;load into the counter
  514.            rep movsb              ;Copy string
  515.  
  516.            mov   al,0dH           ;Add carriage return
  517.            stosb
  518.  
  519.            ;-- Transfer filename from command line to FCBs -----------------
  520.  
  521.            push  cs               ;Transfer CS to DS
  522.            pop   ds
  523.  
  524.            mov   si,offset CmdBuf+1 ;DS:SI points to CmdBuf + 1
  525.            mov   di,offset FCB1   ;ES:DI points to FCB #1
  526.            mov   ax,2901h         ;Function no.:"Transfer filename to FCB"
  527.            int   21h              ;Call DOS interrupt
  528.  
  529.            mov   di,offset FCB2   ;ES:DI now points to FCB #2
  530.            mov   ax,2901h         ;Function no.: "Transfer filename to FCB"
  531.            int   21h              ;Call DOS interrupt
  532.  
  533.            mov   ds,dx            ;Move old value into DS
  534.  
  535.            ;-- Transfer remaining parameters to variables ------------------
  536.  
  537.            les   ax,ALen          ;Change length
  538.            mov   word ptr Len + 2,es
  539.            mov   word ptr Len,ax
  540.  
  541.            mov   al,AToDisk       ;Change disk flag
  542.            mov   ToDisk,al
  543.  
  544.            mov   ax,AHandle       ;Change handle
  545.            mov   Handle,ax
  546.  
  547.            push  ds               ;Push DS onto the stack
  548.  
  549.            ;-- Exchange variables and program code between labels CodeStart -
  550.            ;-- and CodeEnd with the contents of the PSP code segment
  551.  
  552.            mov   ax,PrefixSeg             ;ES:DI points to start of Turbo
  553.            add   ax,10h                   ;program following PSP
  554.            mov   TurboSeg,ax              ;Mark addr. of Turbo code segment
  555.            mov   es,ax
  556.            xor   di,di
  557.  
  558.            push  cs                       ;Set DS to CS
  559.            pop   ds
  560.            assume cs:code, ds:code
  561.  
  562.            mov   si,offset CodeStart      ;DS:SI points to CodeStart
  563.            and   si,0FFF0h                ;Round off at start of paragraph
  564.  
  565.            mov   cx,CostLen               ;Get number of words to be swapped
  566.            mov   word ptr CoStAddr,si     ;Mark address of
  567.            mov   word ptr CoStAddr + 2,ds ;PARA(Codestart)
  568.  
  569.            mov   dx,es            ;Mark target segment in DX
  570.            cld                    ;Increment on SI/DI string instructions
  571.  
  572.            ;-- Swap loop ---------------------------------------------------
  573.  
  574. dl_loop:   mov   ax,[si]          ;Load word from assembler module
  575.            mov   bx,es:[di]       ;Load word from Turbo Pascal program
  576.            stosw                  ;Write assm. module word to Turbo program
  577.            mov   [si],bx          ;Write Turbo program word to assm. module
  578.            inc   si               ;Set SI to next word
  579.            inc   si               ;(increment SI through STOSW)
  580.            loop  dl_loop          ;Use all words
  581.  
  582.            ;-- Adapt segment address of code segment before calling the ---
  583.            ;-- StartSwap procedure so that variable references to the code
  584.            ;-- segment remain unchanged
  585.  
  586.            mov   ax,offset CodeStart ;Compute number of paragraphs between
  587.            mov   cl,4                ;CodeStart and the start of the
  588.            shr   ax,cl               ;segment, and get segment address in
  589.            sub   dx,ax               ;DX
  590.  
  591.  
  592.            push  cs                  ;Return address to BACK label
  593.            mov   ax,offset back      ;Move onto the stack
  594.            push  ax
  595.  
  596.            push  dx                  ;Push segment address onto stack
  597.            mov   ax,offset StartSwap ;Move offset address onto stack
  598.            push  ax
  599.  
  600.            retf                      ;FAR-RET to StartSwap
  601.  
  602. back:      ;----------------------------------------------------------------
  603.            ;-- Returns original program to main memory and executes the
  604.            ;-- program.
  605.            ;-- Registers have the following contents:
  606.            ;--   DS:SI = End of assembler code following the PSP
  607.            ;--   ES:DI = End of Turbo code in the SWAP unit
  608.            ;--   CX    = Number of words
  609.            ;----------------------------------------------------------------
  610.  
  611.            assume cs:code, ds:nothing
  612.  
  613.            std                    ;Decrement string instructions by SI/DI
  614.  
  615.            ;-- Swap back loop ----------------------------------------------
  616.  
  617. ul_loop:   mov   bx,es:[di]       ;Get byte from old memory range
  618.            mov   ax,[si]          ;Get byte from current memory range
  619.            mov   [si],bx          ;Byte from old memory rng to current rng
  620.            dec   si               ;Set SI to previous word
  621.            dec   si
  622.            stosw                  ;Byte from current memory rng to old rng
  623.            loop  ul_loop          ;Repeat until memory ranges are exchanged
  624.  
  625.            pop   ds               ;Pop DS off of stack
  626.            assume ds:data
  627.  
  628.            pop   bp               ;Pop BP
  629.  
  630.            ;-- MOV SP,BP must not be given, since SP doesn't change
  631.  
  632.            xor   ah,ah            ;Place error code in AX
  633.            mov   al,Error_Code
  634.  
  635.            ret ARG_LEN            ;Return to caller, clear arguments 
  636.                                   ;from stack
  637.  
  638. SwapOutAndExec endp
  639.  
  640.  
  641. ;---------------------------------------------------------------------------
  642. ;-- InitSwapa : Computes the number of bytes/words allocated for a program
  643. ;--             swap with the start of the Turbo program in memory
  644. ;-- Input        : none
  645. ;-- Output       : number of bytes
  646. ;-- Pascal call  : function InitSWapa : word;
  647. ;-- Info         : This procedure must be called before the 
  648. ;--                first call to SwapOutAndExec!
  649.  
  650. InitSwapa  proc near
  651.  
  652.            assume cs:code, ds:data
  653.  
  654.            mov   bx,offset CodeStart      ;AX points to start of code
  655.            and   bx,0FFF0h                ;Round off at start of paragraph
  656.            mov   ax,offset CodeEnd        ;BX points to end of code
  657.            sub   ax,bx                    ;Compute number of bytes
  658.            inc   ax                       ;Convert CX to words
  659.            shr   ax,1
  660.            mov   CoStLen,ax               ;Mark number of words to be swapped
  661.            shl   ax,1                     ;Convert to bytes
  662.  
  663.            ;-- Return contents of AX as function result
  664.  
  665.            ret                            ;Return to caller
  666.  
  667. InitSwapa  endp
  668.  
  669. ;---------------------------------------------------------------------------
  670.  
  671. CODE       ends                   ;End of code segment
  672.            end                    ;End of program
  673.